/*
 *  Copyright (C) 2021 Texas Instruments Incorporated
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include <ecat_def.h>
#include <applInterface.h>

#include <string.h> /* for memset */
#include <tiescfoe.h>

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

#if FOE_SUPPORTED

extern unsigned char bBootMode; /**< \brief Indicates in slave is in BOOT mode*/

static uint8_t foe_download_flag;
static uint8_t file_write_offset;

/*Section of RAM chosen to store FoE Data*/
#define S0RAM_BASE                0x20000000U;

uint8_t *ptr = S0RAM_BASE;

#endif /* FOE_SUPPORTED */

/* ========================================================================== */
/*                       Function Declarations                                */
/* ========================================================================== */

/*-----------------------------------------------------------------------------------------
------
------    application specific functions
------
-----------------------------------------------------------------------------------------*/

#if FOE_SUPPORTED
/**
*  \brief This function should be called when a firmware download command is received
*         from EtherCAT master
*
*  \param password password received from master
*/
void tiesc_start_foe_download(uint32_t password);

/**
*  \brief Stores the received data as part of firmware download from EtherCAT master.
*         This may get called multiple times during firmware download. This function
*         performs OSPI flash writes for every 256-bytes received from master.
*
*  \param pData Pointer to data buffer
*  \param Size  Number of bytes received
*/

void tiesc_store_foe_data(uint16_t *pData, uint16_t Size);

uint16_t tiesc_foe_read(uint16_t *pName, uint16_t nameSize, uint32_t password,
                        uint16_t maxBlockSize, uint16_t *pData);

uint16_t tiesc_foe_read_data(uint32_t offset, uint16_t maxBlockSize,
                             uint16_t *pData);

uint16_t tiesc_foe_read_data(uint32_t offset, uint16_t maxBlockSize,
                             uint16_t *pData);

uint16_t tiesc_foe_write_data(uint16_t *pData, uint16_t Size,
                              unsigned char bDataFollowing);

uint16_t tiesc_foe_write(uint16_t *pName, uint16_t nameSize, uint32_t password);
#endif /* FOE_SUPPORTED */

/* ========================================================================== */
/*                       Function Defintions                                  */
/* ========================================================================== */

/*-----------------------------------------------------------------------------------------
------
------    generic functions
------
-----------------------------------------------------------------------------------------*/

#if FOE_SUPPORTED

void tiesc_start_foe_download(uint32_t password)
{
    foe_download_flag = 1;
}

/* Function to store Data received from FoE operation*/
void tiesc_store_foe_data(uint16_t *pData, uint16_t Size)
{
    int i;

    for(i=0;i<Size/2;i++)
    {
        /*Writing data to prescribed memory location*/
        uint8_t a = pData[i] >> 8;
        uint8_t b = pData[i];
        memset(ptr + file_write_offset, b, 1);
        file_write_offset++;
        memset(ptr + file_write_offset, a, 1);
        file_write_offset++;
    }
}

void tiesc_boot_2_init_handler()
{
    if(foe_download_flag)
    {
        /* Reset the flag */
        foe_download_flag = 0;
    }
}

/*Dummy function defined, functionality not supported here*/
uint16_t tiesc_foe_read(uint16_t *pName, uint16_t nameSize, uint32_t password,
                        uint16_t maxBlockSize, uint16_t *pData)
{
    return TIESC_ECAT_FOE_ERRCODE_NOTFOUND;
}

/*Dummy function defined, functionality not supported here*/
uint16_t tiesc_foe_read_data(uint32_t offset, uint16_t maxBlockSize,
                             uint16_t *pData)
{
    return maxBlockSize;
}

/* Function called Subsequently for every FoE Write Block*/
uint16_t tiesc_foe_write_data(uint16_t *pData, uint16_t Size,
                              unsigned char bDataFollowing)
{
  if(bBootMode)
  {
      tiesc_store_foe_data(pData, Size);
      return 0;
  }
  else
  {
      return TIESC_ECAT_FOE_ERRCODE_BOOTSTRAPONLY;
  }
}

/* Function called to initiate FoE Write Operation*/ 
uint16_t tiesc_foe_write(uint16_t *pName, uint16_t nameSize, uint32_t password)
{
  if(bBootMode)
  {
      tiesc_start_foe_download(password);
      return 0;
  }
  else
  {
      return TIESC_ECAT_FOE_ERRCODE_BOOTSTRAPONLY;
  }
}

#endif /* FOE_SUPPORTED */

/* Initialises FoE Related functions to be called by the stack*/
void tiesc_foe_init(void)
{
#if FOE_SUPPORTED
    pAPPL_FoeRead = tiesc_foe_read;
    pAPPL_FoeReadData = tiesc_foe_read_data;
    pAPPL_FoeWriteData = tiesc_foe_write_data;
    pAPPL_FoeWrite = tiesc_foe_write;
    foe_download_flag = 0;
#endif
}
